package com.google.code.sysarch.v4.network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import com.google.code.sysarch.v4.graphical.Game;
import com.google.code.sysarch.v4.main.BattleShips;

public class NetworkThread extends Thread {
	
	boolean isServer;
	String host = "";
	int port = 2312;	// fixed port
	Socket mySocket;
	boolean connected = false;
	boolean quit = false;
	int command,field;
	InputStream in;
	OutputStream out;
	NetworkCommandList NCL = null;
	
	
	/**
	 * constructor if we are a server
	 */
	public NetworkThread() {
		isServer = true;

		NCL = new NetworkCommandList();
	}
	
	
	public NetworkCommand getCommand() {
		return NCL.get();
	}
	
	/**
	 * @return true if the program runs in server mode
	 */
	public boolean isServer() {
		return isServer;
	}
	
	
	/**
	 * constructor if we are a server
	 */
	public NetworkThread(String host) {
		isServer = false;
		this.host = host;
		
		NCL = new NetworkCommandList();
	}
	
	
	public void run() {
		Game g = null;
		int field_low, field_high;
		
		while (!quit) {
			try {

				if (isServer) {
					//BattleShips.loadingWnd.display();
					BattleShips.loadingWnd.setState("Warte auf Verbindung...");
					System.out.println("NETWORK: Server-Modus");
					ServerSocket serverSocket = new ServerSocket(port);
				
		        	InetAddress inet;
		    	
		        	try {
		            	inet = InetAddress.getLocalHost();
		            	System.out.println("NETWORK: Hostname: "+inet.getHostName());
		        	} catch (UnknownHostException e) {} 

					System.out.println("NETWORK: Warte auf Verbindung...");
					mySocket = serverSocket.accept();

				} else {
					System.out.println("NETWORK: Client-Modus");
			
					System.out.println("NETWORK: Stelle Verbindung her...");			
					mySocket = new Socket(host, port);
				}

				System.out.println("NETWORK: Getting Streams...");
				out = mySocket.getOutputStream();
				in = mySocket.getInputStream();
			
				connected = true;	
			
			} catch (UnknownHostException e) {
				e.printStackTrace();
				connected = false;
				System.out.println("NETWORK: Disconnect #4 :-(");
			} catch (IOException e) {
				//e.printStackTrace();
				connected = false;
				System.out.println("NETWORK: Connection cannot be established. Retrying in 2s.");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				System.out.println("NETWORK: Retrying NOW...");				
			}
			
			if (connected) {
			
				if ((isServer) && (g == null)) {
					g = new Game("Schiffe versenken");
					new Thread(g).start();
				}
		
				System.out.println("NETWORK: Connection succesfully established.");
				while (connected) {
					try {					
						command = in.read();
					
						while (command > 0) {
							field_low = in.read();
							field_high = in.read();
							field = field_low + (field_high << 8);
							//System.out.println("NETWORK: Command: " + command);
							//System.out.println("NETWORK: Field: " + field);
							NCL.add(command, field);
							command = in.read();
						}
					
						try {
							sleep(20);
						} catch (InterruptedException e) {}
					
					} catch (IOException e) {
						connected = false;
						System.out.println("NETWORK: Disconnect #2 :-(");
					}
				}		
			} // if
			
		}
		System.out.println("NETWORK: Ending thread.");
	} // run
	

	public synchronized void send(int command) {
		send(command, 42);
	}

	
	/**
	 * sends a command through a connection
	 * @param command
	 * @param field
	 */
	public synchronized void send(int command, int field) {
		/// wait for a connection
		while (!connected) {
			try {
				sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		//System.out.println("NETWORK: Sending "+command+" at "+field+"...");
		try {
			out.write(command);
			out.write(field);
			out.write(field >>> 8);
		} catch (IOException e) {
			connected = false;
			System.out.println("NETWORK: Disconnect #3 :-(");
		}
	}
	
	
	public NetworkCommand get() {
		if (NCL == null) return null; else return NCL.get();		
	}
	
	
	/**
	 * ends the connection and the thread dies
	 */
	void disconnect() {
		try {
			mySocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		quit = true;
	}

}
